package com.af.example;

import java.util.Optional;

/**
 * @author : zhenyun.su
 * @comment : Optional 如何使用
 *  用法： 创建或获取Optional
 *        1. Optional.ofNullable(user) 不能确认user是否为空时使用  2. Optional.of(user) 可确定user一定不为空，否则抛出异常
 *        2. spring-data-jpa, findById()及Stream对象, 也是返回Optional
 *        获取值
 *        userOptional2.orElse(null);
 *        userOptional2.orElseGet(()->createUser("test3", "3333333333333"));
 *        userOptional2.orElseThrow(()->new Exception("user can not null"));
 *  推荐场景： 一般用于处理返回值， 或为其他api提供 Optional返回值， 不适合应用在class成员中，或参数中
 *  说你： Optional只是为简化空异常的处理 NullPointerException
 * @since : 2022/5/24
 */

public class AfOptionalExample {
    public static User createUser(String name, String mobile){
        System.out.println("create user: "+name+";"+mobile);
        User user = new User(name, mobile);
        user.setName(name);
        user.setMobile(mobile);
        return user;
    }


    public static void main(String[] args) {
        System.out.println("1 如何创建Optional");
        // 创建一个空值的 Optional
        Optional<User> userOptional= Optional.empty();
        User user = null;
        // 创建一个user值的 Optional, user 为空，of函数抛出异常 NullPointerException
        // Optional<User> userOptional1= Optional.of(user);
        // ofNullable() 函数允许value为空， 当为空时，等同empty()
        Optional<User> userOptional2= Optional.ofNullable(user);
        user = createUser("zhenyun.su", "12345678901");
        Optional<User> userOptional3= Optional.of(user);

        System.out.println("如何获取value使用");
        User user1 = null;
        // 1. 通过get()函数获取
        // value为空，则抛出异常：NoSuchElementException
        // user1 = userOptional2.get();
        // value不为为空，正常获取
        user1 = userOptional3.get();

        // 2. T orElse(T other) 函数获取

        User newUser = new User("zhenyun.su2", "12345678901");
        user1 = userOptional2.orElse(newUser);
        System.out.println(user1);
        // 特别注意的是，参数other为 方法时， 不管 userOptional2是否为空，都会被执行一次
        user1 = userOptional2.orElse(createUser("test2", "222222222222"));
        System.out.println(user1);
        user1 = userOptional3.orElse(null);
        System.out.println(user1);

        // 2. T orElseGet(Supplier<? extends T> other) 函数获取
        // 若值为空时， 则执行Supplier函数式接口的实现方法createUser，创建user
        user1 = userOptional2.orElseGet(()->createUser("test3", "3333333333333"));
        System.out.println(user1);
        user1 = userOptional3.orElseGet(()->createUser("test4", "4444444444444"));
        System.out.println(user1);

        // 3. <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier)
        // 若为空，则直接抛出可自定义的异常
        try {
            user1 = userOptional2.orElseThrow(()->new Exception("user can not null"));
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }

        // 判断为空， isPresent() true表示value不为空
        if (userOptional2.isPresent()) {
            System.out.println("userOptional2 value is not null");
        }


        System.out.println("4如何转换值");
        user1 = createUser("asu1", "123456");
        // map 会构建一个moble的optional, mobile 为空，则取123456
        String mobile = Optional.ofNullable(user1).map(u -> u.getMobile()).orElse("123456");
        String name = Optional.ofNullable(user1).map(u -> u.getName()).orElse("asu2");
        System.out.println(mobile);
        System.out.println(name);

    }

    public static void print(Object user){
        System.out.println(user);
    }

    public static class User{
        private String name;
        private String mobile;

        public User(String name, String mobile) {
            this.name = name;
            this.mobile = mobile;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getMobile() {
            return mobile;
        }

        public void setMobile(String mobile) {
            this.mobile = mobile;
        }

        @Override
        public String toString() {
            return "User{" +
                    "name='" + name + '\'' +
                    ", mobile='" + mobile + '\'' +
                    '}';
        }
    }
}
